package cn.gdut.chengcai.base;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

public class MailSmtpUtil {

	protected Properties props;
	protected MimeMessage message;
	private Multipart mp; // Multipart对象,邮件内容,标题,附件等内容均添加到其中后再生成MimeMessage对象
	protected String toAddress;

	public static MailSmtpUtil getDefaultInstance() throws MessagingException {
		InputStream is = null;
		String smtpHost = "";
		String username = "";
		String password = "";
		try {
			is = ClassLoader.getSystemResourceAsStream("mail.properties");
			Properties p = new Properties();
			p.load(is);
			smtpHost = p.get("mail.smtp.host").toString();
			username = p.get("mail.user").toString();
			password = p.get("mail.password").toString();
		} catch (IOException ioe) {
			ioe.printStackTrace();
		} finally {
			IOUtils.closeQuietly(is);
		}
		return new MailSmtpUtil(smtpHost, username, password);
	}

	public static MailSmtpUtil getNewInstance(String smtpHost, String username, String password)
			throws MessagingException {
		return new MailSmtpUtil(smtpHost, username, password);
	}

	public static MailSmtpUtil getNewInstance(String username, String password) throws MessagingException {
		return new MailSmtpUtil(findSmtpHost(username), username, password);
	}

	private MailSmtpUtil(String smtpHost, String username, String password) throws MessagingException {
		// 配置发送邮件的环境属性
		props = new Properties();
		/*
		 * 可用的属性： mail.store.protocol / mail.transport.protocol / mail.host /
		 * mail.user / mail.from
		 */
		// 表示SMTP发送邮件，需要进行身份验证
		props.put("mail.smtp.auth", "true");
		if (smtpHost.indexOf(":") > 0) {
			String[] smtpHosts = smtpHost.split(":");
			props.put("mail.smtp.host", smtpHosts[0]);
			props.put("mail.smtp.port", smtpHosts[1]);
		} else {
			props.put("mail.smtp.host", smtpHost);
			props.put("mail.smtp.port", "25");
		}

		// 发件人的账号
		props.put("mail.user", username);
		// 访问SMTP服务时需要提供的密码
		props.put("mail.password", password);

		// 构建授权信息，用于进行SMTP进行身份验证
		MyAuthenticator authenticator = new MyAuthenticator(username, password);

		// 使用环境属性和授权信息，创建邮件会话
		Session mailSession = Session.getInstance(props, authenticator);

		// 创建邮件消息
		message = new MimeMessage(mailSession);
		mp = new MimeMultipart();

		// 设置发件人
		InternetAddress form = new InternetAddress(username);
		message.setFrom(form);
	}

	private class MyAuthenticator extends Authenticator {
		private String userName;
		private String password;

		public MyAuthenticator(String userName, String password) {
			this.userName = userName;
			this.password = password;
		}

		protected PasswordAuthentication getPasswordAuthentication() {
			return new PasswordAuthentication(userName, password);
		}
	}

	/**
	 * 设置收件人
	 */
	public void addTo(String toAddress) throws MessagingException {
		this.toAddress = toAddress;

		InternetAddress to = new InternetAddress(toAddress);
		message.addRecipient(RecipientType.TO, to);
	}

	/**
	 * 设置抄送
	 */
	public void addCc(String ccAddress) throws MessagingException {
		InternetAddress cc = new InternetAddress(ccAddress);
		message.addRecipient(RecipientType.CC, cc);

	}

	/**
	 * 设置密送（其他的收件人不能看到密送的邮件地址）
	 */
	public void addBcc(String bccAddress) throws MessagingException {
		InternetAddress bcc = new InternetAddress(bccAddress);
		message.addRecipient(RecipientType.BCC, bcc);

	}

	/**
	 * 添加附件
	 */
	public boolean addAttachment(String filename) {
		try {
			BodyPart bp = new MimeBodyPart();
			FileDataSource fileds = new FileDataSource(filename);
			bp.setDataHandler(new DataHandler(fileds));
			bp.setFileName(fileds.getName());

			mp.addBodyPart(bp);

			return true;
		} catch (Exception e) {
			return false;
		}

	}

	/**
	 * 设置邮件标题
	 */
	public void setSubject(String subject) throws MessagingException {
		message.setSubject(subject);
	}

	/**
	 * 设置邮件的内容体
	 */
	public boolean setContent(String content) throws MessagingException {
		try {
			BodyPart bp = new MimeBodyPart();
			bp.setContent("" + content, "text/html;charset=UTF-8");
			mp.addBodyPart(bp);

			return true;
		} catch (Exception e) {
			System.err.println("设置邮件正文时发生错误！" + e);
			return false;
		}
	}

	/**
	 * 发送邮件
	 */
	public boolean send() {
		boolean result = false;

		if (StringUtils.isEmpty(toAddress) == true) {
			return result;
		}

		try {
			message.setContent(mp);
			message.saveChanges();

			// 发送邮件
			Transport.send(message);

			result = true;
		} catch (MessagingException e) {
			e.printStackTrace();
		}

		return result;
	}

	/**
	 * 发送邮件
	 */
	public void send(ResponseData<Object> response) {
		response.setIsSuccess(false);

		if (StringUtils.isEmpty(toAddress) == true) {
			response.setMessage("收件人地址为空");
		}

		try {
			message.setContent(mp);
			message.saveChanges();

			// 发送邮件
			Transport.send(message);

			response.setIsSuccess(true);
		} catch (MessagingException e) {
			response.setMessage(analyzerMailError(e.getLocalizedMessage()));
			e.printStackTrace();
		}
	}

	private String analyzerMailError(String errorMessage) {
		if (errorMessage.contains("Could not connect to SMTP host") == true) {
			return "无法连接到SMTP主机";
		} else if (errorMessage.contains("535 Error") == true) {
			return "SMTP服务器需要身份验证失败，用户名或者密码错误";
		} else if (errorMessage.contains("Invalid Addresses") == true) {
			return "收件人或者抄送人或者密送人邮箱地址不正确";
		}
		return "未知错误";
	}

	public static String findSmtpHost(String email) {
		String result = "";
		String smtpType = "";
		Pattern p = Pattern.compile("@(.*).com");
		Matcher m = p.matcher(email);
		if (m.find()) {
			smtpType = m.group(1);
			if (smtpType.endsWith("qq")) {
				return "smtp.qq.com:465";
			} else {
				return "smtp." + smtpType + ".com:25";
			}
		}

		return result;
	}
}